﻿using UnityEngine;
using Core;
using System.Collections;
using UnityEngine.SceneManagement;

namespace Core
{
    internal class SceneSystem : EntitySystem, IAwake
    {
        private bool isLoading = false;
        private string currentScenePath = string.Empty;
        private object loadSceneData = null;

        public void Awake()
        {
            Subscribe<LoadScene>(LoadScene);
        }

        public void LoadScene(ref LoadScene data)
        {
            var scenePath = data.scenePath;
            
            if (currentScenePath == scenePath)
            {
                Debug.Log($"The scene is already loaded: {scenePath}");
                return;
            }

            if (isLoading)
            {
                Debug.Log($"Scene is loading:{currentScenePath}");
                return;
            }

            isLoading = true;
            loadSceneData = data.data;

            LoadSceneOperation(scenePath);
        }

        private async void LoadSceneOperation(string scenePath)
        {
            new OnLoadSceneBegin() { path = scenePath }.Publish();

            var asyncOperation = await new LoadSceneAssetBundleAsync(scenePath).PublishAsync();
            var sceneBundle = asyncOperation.sceneBundle;

            if (sceneBundle == null)
            {
                ClearLoadSceneData();
                return;
            }

            var paths = sceneBundle.GetAllScenePaths();
            if (paths.Length != 1)
            {
                Debug.Log($"这不是一个单一的场景资源包：{scenePath}，加载场景失败。");
                ClearLoadSceneData();
                return;
            }

            new StartCoroutine(LoadSceneProgress(scenePath, paths)).Publish();
        }

        private IEnumerator LoadSceneProgress(string scenePath, string[] paths)
        {
            var operation = SceneManager.LoadSceneAsync(paths[0]);
            operation.allowSceneActivation = true;

            while (!operation.isDone)
            {
                new OnLoadSceneProgress(operation.progress).Publish();
                yield return null;
            }

            LoadSceneDone(scenePath);
        }

        private void LoadSceneDone(string scenePath)
        {
            isLoading = false;

            new ForceGCAsset().Publish();
            new OnLoadSceneEnd(scenePath).Publish();

            var sceneMono = GameObject.FindObjectOfType<BaseScene>();
            if (sceneMono != null)
            {
                sceneMono.AddAssetReference(scenePath);
                sceneMono._OnInit(loadSceneData);
            }
            else
            {
                Debug.LogError("未找到有BaseScene类型脚本挂载在场景中。");
            }

            ClearLoadSceneData();
        }

        private void ClearLoadSceneData()
        {
            loadSceneData = null;
        }
    }
}

